﻿using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;

using GameEngine;
using DaphneProfiBase;
using System.Windows;

namespace DaphneControls.ViewModel
{
    /// <summary>
    /// Container for notification of button position
    /// </summary>
    public class ButtonPosition
    {
        public double X
        { get; set; }

        public double Y
        { get; set; }

        public double Width
        { get; set; }

        public double Height
        { get; set; }
    }

    /// <summary>
    /// View Model for user control editing the PDN Tags
    /// </summary>
    public class PDNTagEditorVM : ViewModelBase
    {
        private GameManager _gameManager = null;

        /// <summary>
        /// Initializes a new instance of the PDNTagEditorVM class.
        /// </summary>
        public PDNTagEditorVM()
        {
            AddPDNTag = new RelayCommand(this.AddPDNTagExecute, () => { return true; } );
            DeletePDNTag = new RelayCommand<PDNTagRecord>(rec => this.DeletePDNTagExecute(rec),
                (rec) => { return true; });
                    

            // register notification message of add button position
            Messenger.Default.Register<NotificationMessage<ButtonPosition>>(this, (nm) =>
            {
                if (nm.Notification == "AddButtonPosition")
                {
                    AddButtonLeft = nm.Content.X;
                    AddButtonTop = nm.Content.Y;
                    AddButtonWidth = nm.Content.Width;
                    AddButtonHeight = nm.Content.Height;
                }
            });

            // register message for the setting of the current game manager
            Messenger.Default.Register<NotificationMessage<GameManager>>(this, (nm) =>
            {
                if (nm.Notification == Notify.SetGameManager)
                {
                    _gameManager = nm.Content;
                }
            });

            // register message for updating the PDN Tag Content
            Messenger.Default.Register<NotificationMessage<PDNTagRecord>>(this, (nm) =>
            {
                if (nm.Notification == Notify.PDNTagUpdated)
                {
                    UpdatePDNTagExecute(nm.Content);
                }
            });
        }

        /// <summary>
        /// Add Command Binding Property
        /// </summary>
        public RelayCommand AddPDNTag
        { get; set; }

        /// <summary>
        /// Delete Command Binding Property
        /// </summary>
        public RelayCommand<PDNTagRecord> DeletePDNTag
        { get; set; }

        /// <summary>
        /// Record binding property
        /// </summary>
        public List<PDNTagRecord> TagRecords
        {
            get
            {
                return GetPDNTagList();
            }
        }

        /// <summary>
        /// Add button coordinates
        /// </summary>
        public double AddButtonLeft
        { get; set; }

        public double AddButtonTop
        { get; set; }

        public double AddButtonWidth
        { get; set; }

        public double AddButtonHeight
        { get; set; }

        /// <summary>
        /// Executes adding PDN Tag
        /// </summary>
        private void AddPDNTagExecute()
        {
            if (_gameManager == null)
                return;
                                
            // run form for adding a new PDN tag
            PDNTagAddForm frm = new PDNTagAddForm();
            PDNTagAddVM vm = new PDNTagAddVM(_gameManager.PDNHeaders.Keys.ToList(), _gameManager);
            frm.DataContext = vm;

            // set position
            const double marginY = 5;
            double frmX = AddButtonLeft + AddButtonWidth - frm.Width;
            double frmY = AddButtonTop + AddButtonHeight + marginY;
            frm.Left = frmX;
            frm.Top = frmY;

            frm.ShowDialog();
            // when the new PDN Tag selected
            if (vm.SelectionDone == true)
            {
                _gameManager.PDNHeaders[vm.SelectedPDNTag] = string.Empty;
                RaisePropertyChanged("TagRecords");
            }
        }

        /// <summary>
        /// Updates the PDN Tag Content
        /// </summary>
        private void UpdatePDNTagExecute(PDNTagRecord rec)
        {
            _gameManager.PDNHeaders[rec.TagHeader] = rec.TagContent;
            RaisePropertyChanged("TagRecords");
        }

        /// <summary>
        /// Deletes the PDN tag
        /// </summary>
        /// <param name="rec"></param>
        private void DeletePDNTagExecute(PDNTagRecord rec)
        {
            // confirmation dialog
            if (MessageBox.Show("Are you sure to delete this PDN tag", "Delete confirmation", MessageBoxButton.YesNo)
                != MessageBoxResult.Yes)
            {
                return;
            }
           
            // remove the PDN tag
            _gameManager.PDNHeaders.Remove(rec.TagHeader);
            RaisePropertyChanged("TagRecords");
        }

        /// <summary>
        /// Returns the list for binding to the datagrid
        /// </summary>
        private List<PDNTagRecord> GetPDNTagList()
        {

            // create an empty list
            List<PDNTagRecord> lstTags = new List<PDNTagRecord>();

            if (_gameManager == null)
                return lstTags;

            // convert the model
            foreach (var pair in _gameManager.PDNHeaders)
            {
                PDNTagRecord rec = new PDNTagRecord();
                rec.TagHeader = pair.Key;
                rec.TagContent = pair.Value;
                rec.DeleteCommand = DeletePDNTag;
                rec.CommandParameter = rec;

                lstTags.Add(rec);
            }

            // sort the PDN tags
            var lstAllTags = _gameManager.AllPDNTags;
            lstTags = lstTags.OrderBy(r => lstAllTags.FindIndex(e => e == r.TagHeader)).ToList();

            return lstTags;
        }

    }

    /// <summary>
    /// Container class for the PDN Tags
    /// </summary>
    public class PDNTagRecord
    {
        public string TagHeader
        { get; set; }

        public string TagContent
        { get; set; }

        public RelayCommand<PDNTagRecord> DeleteCommand
        { get; set; }

        public object CommandParameter
        { get; set; }
    }  
 
}